package com.haha.niostudy;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import static com.haha.ByteBufferUtil.debugAll;

@Slf4j
public class Server {
    public static void split(ByteBuffer source){
        source.flip();
        for (int i = 0; i < source.limit(); i++) {
            if(source.get(i)=='\n'){
                int length = i+1-source.position();
                ByteBuffer buffer = ByteBuffer.allocate(length);
                for (int j=0 ;j<length;j++){
                    buffer.put(source.get());

                }
                debugAll(buffer);
            }
        }
        source.compact();
    }
    public static void main(String[] args) throws IOException {
        //1.创建selector
        Selector selector = Selector.open();


        //使用nio来理解阻塞模式
        ByteBuffer buffer = ByteBuffer.allocate(16);
         //1.创建服务器
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);//非阻塞模式
        //2.建立selector 和 channel的联系（注册）
        SelectionKey ssckey = ssc.register(selector, 0, null);
        ssckey.interestOps(SelectionKey.OP_ACCEPT);
        log.debug("register key:{}",ssckey);
        //2.绑定监听端口
        ssc.bind(new InetSocketAddress(8080));
        //3.连接集合
        List<SocketChannel> channelList = new ArrayList<>();
        //3.accept
        while(true){
//            //log.debug("connect...");
//            SocketChannel accept = ssc.accept();//非阻塞，线程还会继续运行，如果没有建立连接，sc为null
//            if(accept!=null){
//                log.debug("connected...{}",accept);
//                accept.configureBlocking(false);
//                channelList.add(accept);
//            }
//
//            //接受客户端发送的数据
//            for(SocketChannel channel : channelList){
//                //log.debug("before read...{}",channel);
//                int read = channel.read(buffer);
//                if(read>0){
//                    buffer.flip();
//                    debugAll(buffer);
//                    buffer.clear();
//                    log.debug("read after...{}",channel);
//                }
//
//            }
            //3.SELECT 方法没有事件发生，线程阻塞，有事件，线程才会恢复运行
            selector.select();
            //4.处理事件,selectedKey 内部包含了所有发生的事件
            Iterator<SelectionKey> selectionKeys = selector.selectedKeys().iterator();
            while (selectionKeys.hasNext()){
                SelectionKey next = selectionKeys.next();
                log.debug("key:{}",next);
                selectionKeys.remove();
                if(next.isAcceptable()){
                    ServerSocketChannel channel = (ServerSocketChannel) next.channel();
                    SocketChannel accept = channel.accept();
                    accept.configureBlocking(false);
                    log.debug("{}",channel);
                    ByteBuffer buffer1 =  ByteBuffer.allocate(16);
                    SelectionKey ssckey1 = accept.register(selector, 0, buffer1);
                    ssckey1.interestOps(SelectionKey.OP_READ);
                    log.debug("{}",channel);

                }else if(next.isReadable()){
                    try{
                        SocketChannel channel = (SocketChannel) next.channel();
                        ByteBuffer attachment = (ByteBuffer) next.attachment();
                        int read = channel.read(attachment);
                        if (read==-1){
                            next.cancel();

                        }else{
//                            attachment.flip();
//                            //debugAll(buffer1);
//                            System.out.println(Charset.defaultCharset().decode(attachment));
                            split(attachment);
                            if(attachment.position()==attachment.limit()){
                                ByteBuffer newBuffer = ByteBuffer.allocate(attachment.capacity()*2);
                                newBuffer.flip();
                                newBuffer.put(attachment);
                                next.attach(newBuffer);
                            }
                        }

                    }catch (IOException e){
                        e.printStackTrace();
                        next.cancel();
                    }

                }

                //                next.cancel();
            }

        }


    }

}
